package com.jjty.dataGenerator.jserji.service;

import com.alibaba.fastjson.JSONObject;
import com.jjty.dataGenerator.jserji.entity.JsDeviceData;
import com.jjty.dataGenerator.jserji.mapper.JsDeviceDataMapper;
import com.jjty.dataGenerator.utils.EncryptUtils;
import com.jjty.dataGenerator.utils.LocationUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class JsDataGeneratorService {
    @Value("${spring.datasource.url}")
    private String dbUrl;
    @Value("${spring.datasource.username}")
    private String dbUsername;
    @Value("${spring.datasource.password}")
    private String dbPassword;

    @Autowired
    private JsDeviceDataMapper deviceDataMapper;

    // AES密钥和初始化向量(实际应用中应从配置文件或环境变量获取)
    private static final String AES_KEY = "c2ea801cb3e94bd2"; // 16字节密钥
    private static final String VIPARA = "88240b9759425ac2";  // 16字节初始向量



    // 江苏省多边形边界坐标点（简化版）
    double[][] jiangsuBoundary = {
            {116.35, 34.60}, {116.55, 34.40}, {116.80, 34.30}, {117.20, 34.20},
            {117.40, 34.00}, {117.90, 33.80}, {118.30, 33.70}, {118.80, 33.50},
            {119.20, 33.30}, {119.60, 33.10}, {120.10, 32.90}, {120.50, 32.80},
            {120.90, 32.70}, {121.20, 32.60}, {121.50, 32.40}, {121.60, 32.20},
            {121.50, 32.00}, {121.30, 31.80}, {121.10, 31.60}, {120.90, 31.40},
            {120.70, 31.30}, {120.40, 31.20}, {120.00, 31.10}, {119.70, 31.00},
            {119.40, 31.00}, {119.10, 31.00}, {118.80, 31.10}, {118.50, 31.30},
            {118.20, 31.50}, {117.90, 31.80}, {117.60, 32.10}, {117.30, 32.40},
            {117.00, 32.70}, {116.80, 33.00}, {116.60, 33.30}, {116.50, 33.60},
            {116.40, 33.90}, {116.35, 34.20}, {116.35, 34.60}
    };

    // 随机数生成器
    //Random random = new Random();

    // 江苏省大致边界框（用于优化随机点生成）
    double minLon = 116.35;
    double maxLon = 121.95;
    double minLat = 30.75;
    double maxLat = 35.15;

    public void generateData(String dataType, int numRecords) {
        Random random = new Random();
        Map<String, String> imeiPhoneMap = getImeiPhoneFromDatabase();

        if (imeiPhoneMap.isEmpty()) {
            System.out.println("未从数据库中获取到IMEI号和手机号码，无法生成数据。");
            return;
        }

        List<String> imeiList = new ArrayList<>(imeiPhoneMap.keySet());
        switch (dataType) {
            case "心跳数据":
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
                String currentDate = dateFormat.format(new Date()); // 提前获取当天日期

                for (int i = 0; i < numRecords; i++) {
                    // 从数据库中随机获取一个imei
                    //String imei = imeiList.get(random.nextInt(imeiList.size()));
                    String imei = "860532072027742";

                    // 生成date (固定为当天日期)
                    String date = currentDate;

                    // 生成step (随机步数，范围：1-30000)
                    int step = random.nextInt(30000) + 1;

                    // 生成power (随机电量百分比，范围：0-100%)
                    int powerValue = random.nextInt(101);
                    String power = powerValue + "%";

                    // 创建数据Map
                    Map<String, Object> dataFields = new HashMap<>();
                    dataFields.put("imei", imei);
                    dataFields.put("date", date);
                    dataFields.put("step", step);
                    dataFields.put("power", power);
                    String encryptedDeviceData = EncryptUtils.AESEncode(JSONObject.toJSONString(dataFields), AES_KEY, VIPARA);

                    // 创建DeviceData对象
                    JsDeviceData deviceData = new JsDeviceData();
                    deviceData.setDataFields(dataFields);
                    deviceData.setDataType(dataType);
                    deviceData.setEncodedData(encryptedDeviceData);

                    // 保存到数据库
                    deviceDataMapper.insert(deviceData);

//                    System.out.println(encryptedDeviceData);
//                    //解密
//                    String decryptedDeviceData = EncryptUtils.AESDecode(encryptedDeviceData, AES_KEY, VIPARA);
//                    System.out.println(decryptedDeviceData);
                }
                break;
            case "短消息上报":
                //Random random = new Random();
                for (int i = 0; i < numRecords; i++) {
                    // 从数据库中随机获取一个imei
                    String imei = imeiList.get(random.nextInt(imeiList.size()));
                    // isRead随机取值0或1
                    int isRead = random.nextInt(2);
                    //todo
                    // 模拟生成消息内容（这里简单示例，可按实际需求调整）
                    String[] sampleMessages = {"今天天气不错", "记得吃晚饭", "早点休息"};
                    String sendMsg = sampleMessages[random.nextInt(sampleMessages.length)];
                    // 发送时间（当前时间往前推一定时间范围内）
                    SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Date now = new Date();
                    long offset = random.nextInt(60 * 60 * 24) * 1000L; // 往前推1天内的随机时间
                    Date sendTime = new Date(now.getTime() - offset);
                    String sendTimeStr = timeFormat.format(sendTime);

                    Map<String, Object> smsDataFields = new HashMap<>();
                    smsDataFields.put("imei", imei);
                    smsDataFields.put("isRead", isRead);
                    smsDataFields.put("sendMsg", sendMsg);
                    smsDataFields.put("sendTime", sendTimeStr);
                    String encryptedSmsData = EncryptUtils.AESEncode(JSONObject.toJSONString(smsDataFields), AES_KEY, VIPARA);
//                    String decryptedDeviceData = EncryptUtils.AESDecode(encryptedSmsData, AES_KEY, VIPARA);
//                    System.out.println(decryptedDeviceData);

                    JsDeviceData smsDeviceData = new JsDeviceData();
                    smsDeviceData.setDataFields(smsDataFields);
                    smsDeviceData.setDataType(dataType);
                    smsDeviceData.setEncodedData(encryptedSmsData);

                    // 保存到数据库
                    deviceDataMapper.insert(smsDeviceData);
                }
                break;
            case "告警通知":


                for (int i = 0; i < numRecords; i++) {
                    // 从数据库中随机获取一个imei
                    String imei = imeiList.get(random.nextInt(imeiList.size()));
                    //String imei = "862074063050571";

                    double lon, lat;
                    // 生成在江苏省多边形内的随机点
                    do {
                        lon = minLon + (maxLon - minLon) * random.nextDouble();
                        lat = minLat + (maxLat - minLat) * random.nextDouble();
                    } while (!isPointInPolygon(lon, lat, jiangsuBoundary));

                    // 模拟生成上报时间（当前时间往前推一定时间范围内，这里简单示例）
                    SimpleDateFormat locationTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Date nowForLocation = new Date();
                    long offsetForLocation = random.nextInt(60 * 60 * 24 * 7) * 1000L; // 往前推7天内的随机时间
                    Date locationTime = new Date(nowForLocation.getTime() - offsetForLocation);
                    String locationTimeStr = locationTimeFormat.format(locationTime);

                    // 调用 LocationUtil 中的方法获取真实地址
                    String locationAddr = LocationUtil.getLocationAddress(String.format("%.7f", lon), String.format("%.7f", lat));
//                    if (locationAddr == null) {
//                        locationAddr = "模拟地址-" + imei;
//                    }

                    // 随机生成告警类型 1或2
                    int alarmType = random.nextInt(2) + 1;

                    Map<String, Object> alarmDataFields = new HashMap<>();
                    alarmDataFields.put("imei", imei);
                    alarmDataFields.put("lon", String.format("%.7f", lon));
                    alarmDataFields.put("lat", String.format("%.7f", lat));
                    alarmDataFields.put("locationTime", locationTimeStr);
                    alarmDataFields.put("locationAddr", locationAddr);
                    alarmDataFields.put("alarmType", alarmType);

                    String encryptedAlarmData = EncryptUtils.AESEncode(JSONObject.toJSONString(alarmDataFields), AES_KEY, VIPARA);

                    JsDeviceData alarmDeviceData = new JsDeviceData();
                    alarmDeviceData.setDataFields(alarmDataFields);
                    alarmDeviceData.setDataType(dataType);
                    alarmDeviceData.setEncodedData(encryptedAlarmData);

                    // 保存到数据库
                    deviceDataMapper.insert(alarmDeviceData);
                }
                break;
            case "电量预警":
                //Random random = new Random();
                for (int i = 0; i < numRecords; i++) {
                    // 从数据库中随机获取一个imei
                    String imei = imeiList.get(random.nextInt(imeiList.size()));
                    //String imei = "862074063050571";
                    // 随机生成告警类型（假设告警类型为1-3之间的整数，可按需调整）
                    String alarmType = String.valueOf(random.nextInt(3) + 1); // 生成1、2或3
                    // 随机生成告警值（假设为0-10之间的百分比，可按需调整）
                    int alarmValue = random.nextInt(11);
                    String alarmValueStr = alarmValue + "%";
                    // 模拟生成告警时间（当前时间往前推一定时间范围内，这里简单示例）
                    SimpleDateFormat createTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Date nowForCreateTime = new Date();
                    long offsetForCreateTime = random.nextInt(60 * 60 * 24) * 1000L; // 往前推1天内的随机时间
                    Date createTime = new Date(nowForCreateTime.getTime() - offsetForCreateTime);
                    String createTimeStr = createTimeFormat.format(createTime);

                    Map<String, Object> warningDataFields = new HashMap<>();
                    warningDataFields.put("imei", imei);
                    warningDataFields.put("alarmType", alarmType);
                    warningDataFields.put("alarmValue", alarmValueStr);
                    warningDataFields.put("createTime", createTimeStr);

                    String encryptedShutdownWarningData = EncryptUtils.AESEncode(JSONObject.toJSONString(warningDataFields), AES_KEY, VIPARA);

                    JsDeviceData warningDeviceData = new JsDeviceData();
                    warningDeviceData.setDataFields(warningDataFields);
                    warningDeviceData.setDataType(dataType);
                    warningDeviceData.setEncodedData(encryptedShutdownWarningData);

                    // 保存到数据库
                    deviceDataMapper.insert(warningDeviceData);
                }
                break;
            case "通话记录":
                //Random random = new Random();
                for (int i = 0; i < numRecords; i++) {
                    // 从数据库中随机获取一个imei
                    String imei = imeiList.get(random.nextInt(imeiList.size()));
                    //String imei = "862074063050571";
                    String phone = imeiPhoneMap.get(imei);
                    // 生成通话开始时间（当前时间往前推一定时间范围）
                    SimpleDateFormat startTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Date nowForStart = new Date();
                    long offsetForStart = random.nextInt(60 * 60 * 24 * 3) * 1000L; // 往前推3天内的随机时间
                    Date startTime = new Date(nowForStart.getTime() - offsetForStart);
                    String startTimeStr = startTimeFormat.format(startTime);
                    // 生成通话结束时间（确保结束时间在开始时间之后，在开始时间基础上增加随机秒数）
                    long randomSeconds = random.nextInt(1200); // 随机增加0 - 1200秒（20min内）
                    Date endTime = new Date(startTime.getTime() + randomSeconds * 1000);
                    String endTimeStr = startTimeFormat.format(endTime);
                    // 计算通话时长
                    long duration = (endTime.getTime() - startTime.getTime()) / 1000;
                    String durationStr = String.valueOf(duration);
                    // 随机生成通话类型 0或1
                    int callType = random.nextInt(2);

                    Map<String, Object> callRecordDataFields = new HashMap<>();
                    callRecordDataFields.put("imei", imei);
                    callRecordDataFields.put("targetPhone", phone);
                    callRecordDataFields.put("startTime", startTimeStr);
                    callRecordDataFields.put("endTime", endTimeStr);
                    callRecordDataFields.put("duration", durationStr);
                    callRecordDataFields.put("callType", callType);

                    String encryptedCallRecordData = EncryptUtils.AESEncode(JSONObject.toJSONString(callRecordDataFields), AES_KEY, VIPARA);

                    JsDeviceData callRecordDeviceData = new JsDeviceData();
                    callRecordDeviceData.setDataFields(callRecordDataFields);
                    callRecordDeviceData.setDataType(dataType);
                    callRecordDeviceData.setEncodedData(encryptedCallRecordData);

                    // 保存到数据库
                    deviceDataMapper.insert(callRecordDeviceData);
                }
                break;
            case "用户位置信息":
                for (int i = 0; i < numRecords; i++) {
                    // 从数据库中随机获取一个imei
                    String imei = imeiList.get(random.nextInt(imeiList.size()));
                    //String imei = "862074063050571";
                    double lon, lat;
                    // 生成在江苏省多边形内的随机点
                    do {
                        lon = minLon + (maxLon - minLon) * random.nextDouble();
                        lat = minLat + (maxLat - minLat) * random.nextDouble();
                    } while (!isPointInPolygon(lon, lat, jiangsuBoundary));
                    // 模拟生成上报时间（当前时间往前推一定时间范围内，这里简单示例）
                    SimpleDateFormat locationTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Date nowForLocation = new Date();
                    long offsetForLocation = random.nextInt(60 * 60 * 24 ) * 1000L; // 往前推1天内的随机时间
                    Date locationTime = new Date(nowForLocation.getTime() - offsetForLocation);
                    String locationTimeStr = locationTimeFormat.format(locationTime);
                    // 调用 LocationUtil 中的方法获取真实地址
                    String locationAddr = LocationUtil.getLocationAddress(String.format("%.7f", lon), String.format("%.7f", lat));
//                    if (locationAddr == null) {
//                        locationAddr = "模拟地址-" + imei;
//                    }

                    Map<String, Object> locationDataFields = new HashMap<>();
                    locationDataFields.put("imei", imei);
                    locationDataFields.put("lon", String.format("%.7f", lon));
                    locationDataFields.put("lat", String.format("%.7f", lat));
                    locationDataFields.put("locationTime", locationTimeStr);
                    locationDataFields.put("locationAddr", locationAddr);

                    String encryptedAlarmData = EncryptUtils.AESEncode(JSONObject.toJSONString(locationDataFields), AES_KEY, VIPARA);

                    JsDeviceData positionInformationData = new JsDeviceData();
                    positionInformationData.setDataFields(locationDataFields);
                    positionInformationData.setDataType(dataType);
                    positionInformationData.setEncodedData(encryptedAlarmData);

                    // 保存到数据库
                    deviceDataMapper.insert(positionInformationData);
                }
                break;

            default:
                throw new IllegalArgumentException("不支持的dataType: " + dataType);
        }
    }
    private Map<String, String> getImeiPhoneFromDatabase() {
        Map<String, String> imeiPhoneMap = new HashMap<>();
        String sql = "SELECT imei, phone_number FROM js_base_data";
        Logger log = LoggerFactory.getLogger(getClass());
        try (Connection conn = DriverManager.getConnection(dbUrl, dbUsername, dbPassword);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {
            while (rs.next()) {
                String imei = rs.getString("imei");
                String phone = rs.getString("phone_number");
                if (imei != null && phone != null) {
                    imeiPhoneMap.put(imei, phone);
                }
            }
        } catch (Exception e) {
            log.error("从数据库查询IMEI号和手机号码时发生异常", e);
        }
        return imeiPhoneMap;
    }

    // 判断点是否在多边形内的方法
    private static boolean isPointInPolygon(double lon, double lat, double[][] polygon) {
        boolean inside = false;
        for (int i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
            double xi = polygon[i][0], yi = polygon[i][1];
            double xj = polygon[j][0], yj = polygon[j][1];

            boolean intersect = ((yi > lat) != (yj > lat))
                    && (lon < (xj - xi) * (lat - yi) / (yj - yi) + xi);
            if (intersect) inside = !inside;
        }
        return inside;
    }



}
